import 'package:xws/helpers/as_t.dart';
import 'package:xws/models/user/user_obj.dart';
import 'package:xws/utils/data_util.dart';

import '../loc_obj.dart';
import 'comment_obj.dart';

/// 物品状态
/// * [SHOWING] 展示中
/// * [DELIVERED] 已送出
enum GoodsStatus { SHOWING, DELIVERED }

const List<String> _msgTypes = <String>['SHOWING', 'DELIVERED'];

extension ExMT on GoodsStatus {
  String get str => _msgTypes[index];
}

GoodsStatus _getType(String k) {
  if (k == 'SHOWING')
    return GoodsStatus.SHOWING;
  else
    return GoodsStatus.DELIVERED;
}

/// 物品对象
class GoodsObj {
  GoodsObj({
    required this.id,
    required this.userId,
    required this.name,
    required this.originalPrice,
    required this.age,
    required this.videoUrl,
    required this.recordUrl,
    required this.description,
    required this.city,
    required this.region,
    required this.latitude,
    required this.longitude,
    required this.geohash,
    required this.count,
    required this.status,
    required this.toUserId,
    required this.createdAt,
    required this.updatedAt,
    required this.likeCount,
    required this.commentCount,
    required this.favoriteCount,
    required this.user,
    required this.photoUrlList,
    required this.distance,
    required this.likeFlag,
    required this.favoriteFlag,
    required this.commentList,
    required this.recordInd,
  });

  factory GoodsObj.fromJson(Map<String, dynamic> jsonRes) {
    final List<String> photoUrlList = <String>[];
    final List<dynamic> pd = jsonRes['photoUrlList'] as List<dynamic>? ?? <dynamic>[];
    if (pd.isNotEmpty) {
      for (final dynamic item in pd) {
        if (item != null) {
          photoUrlList.add(asT<String>(item));
        }
      }
    }

    final List<CommentObj> commentList = <CommentObj>[];
    final List<dynamic> cd = jsonRes['commentList'] as List<dynamic>? ?? <dynamic>[];
    if (cd.isNotEmpty) {
      for (final dynamic item in cd) {
        if (item != null) {
          commentList.add(CommentObj.fromJson(asT<Map<String, dynamic>>(item)));
        }
      }
    }

    return GoodsObj(
      id: asT<String>(jsonRes['id']),
      userId: asT<String>(jsonRes['userId']),
      name: asT<String>(jsonRes['name']),
      originalPrice: asT<double>(jsonRes['originalPrice']),
      age: asT<String>(jsonRes['age']),
      videoUrl: asT<String>(jsonRes['videoUrl']),
      recordUrl: asT<String>(jsonRes['recordUrl']),
      description: asT<String>(jsonRes['description']),
      city: asT<String>(jsonRes['city']),
      region: asT<String>(jsonRes['region']),
      latitude: asT<double>(jsonRes['latitude']),
      longitude: asT<double>(jsonRes['longitude']),
      geohash: asT<String>(jsonRes['geohash']),
      count: asT<int>(jsonRes['count']),
      status: _getType(asT<String>(jsonRes['status'])),
      toUserId: asT<String>(jsonRes['toUserId']),
      createdAt: asT<String>(jsonRes['createdAt']),
      updatedAt: asT<String>(jsonRes['updatedAt']),
      likeCount: asT<int>(jsonRes['likeCount']),
      commentCount: asT<int>(jsonRes['commentCount']),
      favoriteCount: asT<int>(jsonRes['favoriteCount']),
      user: User.fromJson(asT<Map<String, dynamic>>(jsonRes['user'])),
      photoUrlList: photoUrlList,
      distance: km(asT<double>(jsonRes['distance'])),
      likeFlag: asT<bool>(jsonRes['likeFlag']),
      favoriteFlag: asT<bool>(jsonRes['favoriteFlag']),
      commentList: commentList,
      recordInd: 1,
    );
  }

  final String id;
  final String userId;
  late String name;
  late double originalPrice;
  late String age;
  late String videoUrl;
  late String recordUrl;
  late String description;
  late String city;
  late String region;
  late double latitude;
  late double longitude;

  /// 位置geohash
  final String geohash;
  late int count;
  late GoodsStatus status;
  late String toUserId;
  final String createdAt;
  final String updatedAt;
  int likeCount;
  int commentCount;
  int favoriteCount;
  late User user;
  late List<String> photoUrlList;
  final String distance;
  bool likeFlag;
  bool favoriteFlag;
  late List<CommentObj> commentList;

  late double recordInd;

  String get reg => city + region;

  void setLocation(LocObj? loc) {
    if (loc != null) {
      if (loc.city != null) city = loc.city!;
      if (loc.latitude != null) latitude = loc.latitude!;
      if (loc.longitude != null) longitude = loc.longitude!;
      if (loc.district != null) region = loc.district!;
    }
  }

  /// 复制一份
  GoodsObj get copy => GoodsObj.fromJson(toJson());

  bool sameWith(GoodsObj g) => g.toJson() == toJson();

  /// 比对不同的部分
  Map<String, dynamic> different(GoodsObj g) {
    //首先检查长度
    bool isListSame = photoUrlList.length == g.photoUrlList.length;
    if (isListSame) {
      for (int i = 0; i < photoUrlList.length; i++) {
        if (photoUrlList[i] != g.photoUrlList[i]) {
          isListSame = false;
          break;
        }
      }
    }

    name = description;

    name = removeEmoji(name);
    if (name.length > 8) name = name.substring(0, 8);

    return <String, dynamic>{
      'id': id,
      if (name != g.name) 'name': name,
      if (originalPrice != g.originalPrice) 'originalPrice': originalPrice,
      if (age != g.age) 'age': age,
      if (videoUrl != g.videoUrl) 'videoUrl': videoUrl,
      if (recordUrl != g.recordUrl) 'recordUrl': recordUrl,
      if (description != g.description) 'description': description,
      if (city != g.city) 'city': city,
      if (region != g.region) 'region': region,
      if (latitude != g.latitude) 'latitude': latitude,
      if (longitude != g.longitude) 'longitude': longitude,
      if (count != g.count) 'count': count,
      if (!isListSame) 'photoUrlList': photoUrlList,
    };
  }

  void updateFrom(GoodsObj g) {
    name = g.name;
    age = g.age;
    videoUrl = g.videoUrl;
    recordUrl = g.recordUrl;
    description = g.description;
    city = g.city;
    region = g.region;
    latitude = g.latitude;
    longitude = g.longitude;
    count = g.count;
    photoUrlList = g.photoUrlList;
    originalPrice = g.originalPrice;
  }

  void updateAll(GoodsObj g) {
    name = g.name;
    age = g.age;
    videoUrl = g.videoUrl;
    recordUrl = g.recordUrl;
    description = g.description;
    city = g.city;
    region = g.region;
    latitude = g.latitude;
    longitude = g.longitude;
    count = g.count;
    status = g.status;
    toUserId = g.toUserId;
    likeCount = g.likeCount;
    commentCount = g.commentCount;
    favoriteCount = g.favoriteCount;
    user = g.user;
    photoUrlList = g.photoUrlList;
    likeFlag = g.likeFlag;
    favoriteFlag = g.favoriteFlag;
    commentList = g.commentList;
    recordInd = g.recordInd;
    originalPrice = g.originalPrice;
  }

  void updateContent(GoodsObj g) {
    favoriteCount = g.favoriteCount;
    favoriteFlag = g.favoriteFlag;
    likeCount = g.likeCount;
    likeFlag = g.likeFlag;
    commentCount = g.commentCount;
    commentList = g.commentList;
  }

  Map<String, dynamic> toJson() => <String, dynamic>{
        'id': id,
        'userId': userId,
        'name': name,
        'age': age,
        'videoUrl': videoUrl,
        'recordUrl': recordUrl,
        'description': description,
        'city': city,
        'region': region,
        'latitude': latitude,
        'longitude': longitude,
        'geohash': geohash,
        'count': count,
        'status': status,
        'toUserId': toUserId,
        'createdAt': createdAt,
        'updatedAt': updatedAt,
        'likeCount': likeCount,
        'commentCount': commentCount,
        'favoriteCount': favoriteCount,
        'user': user,
        'photoUrlList': photoUrlList,
        'distance': distance,
        'likeFlag': likeFlag,
        'favoriteFlag': favoriteFlag,
        'commentList': commentList,
        'recordInd': recordInd,
        'originalPrice': originalPrice,
      };
}
